﻿#include "FlagsEditEntry.h"
#include <QLabel>
#include "BooleanEditEntry.h"

struct FlagsEditEntry::FlagsEditEntryPrivate {
    QMetaEnum metaEnum;
    QPointer<QLabel> labelInfo;
    QMap<BooleanEditEntry*, int> entryMap;
};

FlagsEditEntry::~FlagsEditEntry() { }

FlagsEditEntry::FlagsEditEntry(QWidget *parent) : EditEntry {parent} {
    p.reset(new FlagsEditEntryPrivate);
    initUi();
}

void FlagsEditEntry::setMetaEnum(const QMetaEnum &metaEnum) {
    p->metaEnum = metaEnum;
    for(int i = 0; i < metaEnum.keyCount(); ++i) {
        const auto entry = new BooleanEditEntry;
        connect(entry, &BooleanEditEntry::valueChanged, this, &FlagsEditEntry::onChidEntryValueChanged);
        p->entryMap.insert(entry, metaEnum.value(i));
        const auto &key = metaEnum.key(i);
        entry->setTitle(tr(key));
        appendChildEntry(entry);
    }
}

void FlagsEditEntry::setValue(int value) {
    QStringList flagNames;

    for(auto &&[entry, data] : p->entryMap.toStdMap()) {
        entry->setValue(value & data);
        if (value & data) {
            flagNames.append(entry->title());
        }
    }

    if(value == 0) {
        flagNames.append(p->metaEnum.key(0));
        if(!p->entryMap.isEmpty()) {
            p->entryMap.key(p->metaEnum.value(0))->setValue(true);
        }
    }

    p->labelInfo->setText(flagNames.join("|"));
}

int FlagsEditEntry::value() const {
    int result = 0;
    for(auto &&[entry, data] : p->entryMap.toStdMap()) {
        if(entry->value()) {
            result |= data;
        } else {
            result &= ~data;
        }
    }
    return result;
}

void FlagsEditEntry::onChidEntryValueChanged() {
    emit valueChanged(value());
}

void FlagsEditEntry::initUi() {
    p->labelInfo = new QLabel;
    addEditControll(p->labelInfo);
}
